﻿using SemenQuest.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SemenQuest
{
    public static class SettingsController
    {
        public static Boolean Running { get; private set; }

        [MethodImpl(MethodImplOptions.Synchronized)]
        public static void Initialize()
        {
            if (!Running)
            {
                Properties.Settings.Default.PropertyChanged += PropertyChanged;
                Running = true;
            }
        }

        private static void PropertyChanged(Object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(PropertyChanged_Callback), e.PropertyName);
        }
        private static void PropertyChanged_Callback(Object args)
        {
            String propertyName = (String)args;
            Object value = Properties.Settings.Default.GetType()
                .GetProperty(propertyName)
                .GetValue(Properties.Settings.Default);
            SettingChangedHandler handler =
                propertyName.StartsWith("Semen") ? SemenSettingChanged :
                propertyName.StartsWith("Egg") ? EggSettingChanged :
                propertyName.StartsWith("Enviroment") ? EnviromentSettingChanged :
                propertyName.StartsWith("Debug") ? DebugSettingChanged :
                null;


            //Fire specific handler first
            if (handler != null)
                foreach (SettingChangedHandler handle in handler.GetInvocationList())
                    handle.BeginInvoke(propertyName, value, EventEndInvoke, null);

            //Fire general handler second
            handler = SettingChanged;
            if (handler != null)
                foreach (SettingChangedHandler handle in handler.GetInvocationList())
                    handle.BeginInvoke(propertyName, value, EventEndInvoke, null);
        }
        private static void EventEndInvoke(IAsyncResult iar)
        {
            var ar = (System.Runtime.Remoting.Messaging.AsyncResult)iar;
            var invokedMethod = (SettingChangedHandler)ar.AsyncDelegate;
            try { invokedMethod.EndInvoke(iar); }
            catch { }
        }


        public delegate void SettingChangedHandler(String setting, Object value);
        public static event SettingChangedHandler SettingChanged;
        public static event SettingChangedHandler SemenSettingChanged;
        public static event SettingChangedHandler EggSettingChanged;
        public static event SettingChangedHandler EnviromentSettingChanged;
        public static event SettingChangedHandler DebugSettingChanged;
    }
}